using System.IdentityModel.Tokens.Jwt;
using System.Security.Cryptography;
using System.Text;
using OneAuthCenter.Domain.Repositories;

namespace OneAuthCenter.API.Middleware;

/// <summary>
/// Token 黑名单验证中间件
/// </summary>
public class TokenBlacklistMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<TokenBlacklistMiddleware> _logger;

    public TokenBlacklistMiddleware(RequestDelegate next, ILogger<TokenBlacklistMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context, IRevokedTokenRepository revokedTokenRepository)
    {
        var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();

        if (!string.IsNullOrEmpty(token))
        {
            try
            {
                var handler = new JwtSecurityTokenHandler();
                var jwtToken = handler.ReadJwtToken(token);

                // 获取 jti (JWT ID)
                var jti = jwtToken.Claims.FirstOrDefault(c => c.Type == JwtRegisteredClaimNames.Jti)?.Value;

                if (!string.IsNullOrEmpty(jti))
                {
                    // 检查 Token 是否在黑名单中
                    var isRevoked = await revokedTokenRepository.IsRevokedAsync(jti);

                    if (isRevoked)
                    {
                        _logger.LogWarning("尝试使用已撤销的 Token: {Jti}", jti);
                        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                        await context.Response.WriteAsJsonAsync(new
                        {
                            error = "token_revoked",
                            error_description = "此 Token 已被撤销"
                        });
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogDebug("Token 解析失败: {Message}", ex.Message);
                // 继续执行，让 JWT 认证中间件处理
            }
        }

        await _next(context);
    }

    /// <summary>
    /// 计算 Token 的 SHA256 哈希
    /// </summary>
    private static string ComputeTokenHash(string token)
    {
        using var sha256 = SHA256.Create();
        var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(token));
        return Convert.ToHexString(hashBytes).ToLower();
    }
}

